/*
 * Copyright (c) 2009 Frederic Daoud
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.stripesbook.rayures.action;

import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import org.stripesbook.rayures.util.MapBundle;
import org.stripesbook.rayures.view.ViewContext;
import org.stripesbook.rayures.view.ViewObject;

/**
 * Base action bean that implements {@link RayuresActionBean}, thus providing support for event handlers
 * that return {@code void}, and for using <i>Rayures tags</i>. This class also provides several
 * convenience methods, as described below.
 *
 * <p>
 * For event handlers that return {@code void}, several {@code forward()} and {@code redirect()}
 * convenience methods are provided to override the default path.
 * </p>
 *
 * <p>
 * The class also provides access to the <i>modular resource bundle</i> via the
 * {@code protected} variable {@code bundle}.
 * </p>
 *
 * <p>
 * Last but not least, provides the {@link #tag(Class)} method for creating <i>Rayures tags</i>.
 * </p>
 *
 * @author Frederic Daoud
 */
public class RayuresBaseActionBean implements RayuresActionBean {
  private Resolution resolution;
  private ViewContext viewContext;

  /** Access to the <i>modular resource bundle</i>. */
  protected MapBundle bundle;

  /* Implementation of ActionBean */

  private ActionBeanContext context;

  public ActionBeanContext getContext() {
    return context;
  }
  public void setContext(ActionBeanContext context) {
    this.context = context;
  }
  
  /* Default path */

  /** Returns {@code getBasePath(getContext().getEventName())}. */
  public String getDefaultPath() {
    return getDefaultPath(getContext().getEventName());
  }

  /** Returns {@code getBasePath(getClass()) + getViewName(viewName) + getViewExtension()}. */
  public String getDefaultPath(String viewName) {
    return getBasePath(getClass()) + getViewName(viewName) + getViewExtension();
  }

  /**
   * Returns the path from which to construct the default view path. This implementation returns the
   * fully qualified class name, prepended with a slash and with all periods replaced with slashes.
   */
  protected String getBasePath(Class<? extends ActionBean> actionBeanClass) {
    return "/" + actionBeanClass.getName().replaceAll("\\.", "/");
  }

  /** Returns the view name, prepended with an underscore. */
  protected String getViewName(String viewName) {
    return "_" + viewName;
  }

  /** Returns ".vm". */
  protected String getViewExtension() {
    return ".vm";
  }

  /* Implementation of RayuresActionBean */

  public ViewContext getViewContext() {
    return viewContext;
  }

  public void setViewContext(ViewContext viewContext) {
    this.viewContext = viewContext;
    this.bundle = viewContext.getBundle();
  }

  public Resolution getResolution() {
    return resolution;
  }
  public void setResolution(Resolution resolution) {
    this.resolution = resolution;
  }

  /**
   * Returns an empty String, "".
   */
  public Object getView() {
    return "";
  }

  /**
   * Creates a <i>Rayures tag</i>.
   *
   * @param type the class of the tag to create.
   */
  protected <T extends ViewObject<?>> T tag(Class<T> type) {
    return ViewObject.tag(type, viewContext);
  }

  /* Forward and redirect convenience methods */

  /** Equivalent of calling {@code setResolution(new ForwardResolution(actionBeanClass));}. */
  public void forward(Class<? extends ActionBean> actionBeanClass) {
    setResolution(new ForwardResolution(actionBeanClass));
  }

  /** Equivalent of calling {@code setResolution(new ForwardResolution(actionBeanClass, event));}. */
  public void forward(Class<? extends ActionBean> actionBeanClass, String event) {
    setResolution(new ForwardResolution(actionBeanClass, event));
  }

  /** Equivalent of calling {@code setResolution(new ForwardResolution(path));}. */
  public void forward(String path) {
    setResolution(new ForwardResolution(path));
  }

  /** Equivalent of calling {@code setResolution(new RedirectResolution(actionBeanClass));}. */
  public void redirect(Class<? extends ActionBean> actionBeanClass) {
    setResolution(new RedirectResolution(actionBeanClass));
  }

  /** Equivalent of calling {@code setResolution(new RedirectResolution(actionBeanClass, event));}. */
  public void redirect(Class<? extends ActionBean> actionBeanClass, String event) {
    setResolution(new RedirectResolution(actionBeanClass, event));
  }

  /** Equivalent of calling {@code setResolution(new RedirectResolution(url));}. */
  public void redirect(String url) {
    setResolution(new RedirectResolution(url));
  }

  /** Equivalent of calling {@code setResolution(new RedirectResolution(url, prependContext));}. */
  public void redirect(String url, boolean prependContext) {
    setResolution(new RedirectResolution(url, prependContext));
  }

  /** Equivalent of calling {@code setResolution(new RedirectResolution(getClass()));}. */
  public void redirectToDefaultEvent() {
    setResolution(new RedirectResolution(getClass()));
  }
}
